﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
using System.Configuration;
using System.Collections;

namespace NHTrace
{
  public partial class FrmMain : Form
  {
    private NHTraceManager _manager;

    public FrmMain()
    {
      InitializeComponent();
    }

    private void webBrowserEx1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
      if (webBrowserEx1.Document.Body != null)
        webBrowserEx1.Document.Window.ScrollTo(0, webBrowserEx1.Document.Body.ScrollRectangle.Height);
    }

    private void FrmMain_Load(object sender, EventArgs e)
    {
      try
      {
        Width = Screen.FromControl(this).Bounds.Width * 80 / 100;
        Left = (Screen.FromControl(this).Bounds.Width - Width) / 2;

        IESoundDisabler.DisableSounds();

        string currPath = Application.ExecutablePath;
        System.Configuration.Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(currPath);
        var cfg = new Config(config);

        string path = cfg.TemplatePath;
        if (!Path.IsPathRooted(path))
          path = Path.Combine(Path.GetDirectoryName(currPath), path);

        _manager = new NHTraceManager(
          cfg.MessagesRefreshTimeInMilliseconds,
          new ReceiverFactory(cfg.ReceiverParameters), 
          new LoggerProvider(cfg.LogCharSize));

        var htmlRenderer = new HtmlMessageRenderer(webBrowserEx1, path);
        _manager.SubscribeRenderer(htmlRenderer);

        var gridRenderer = new GridMessageRenderer(gridMessages);
        _manager.SubscribeRenderer(gridRenderer);

        btnToggle.Checked = cfg.LogEnabled;

        btnStatusBar.Checked = cfg.ShowSatusbar;
        statusStrip1.Visible = cfg.ShowSatusbar;

        btnShowProcess.Checked = cfg.ShowProcess;
        _manager.ShowProcessName = cfg.ShowProcess;

        btnAlwaysOnTop.Checked = cfg.AlwaysOnTop;
        TopMost = cfg.AlwaysOnTop;

        _manager.LogEnabled = cfg.LogEnabled;

        refreshLoggingStatus();
      }
      catch (Exception ex)
      {
        ExceptionHandler.HandleException(ex);
      }
    }

    private void refreshLoggingStatus()
    {
      if (_manager.LogEnabled)
        lblLoggingStatus.Text = "Logging enabled";
      else
        lblLoggingStatus.Text = "Logging disabled";
    }

    private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
    {
      try
      {
        string currPath = Application.ExecutablePath;
        System.Configuration.Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(currPath);

        var cfg = new Config(config);

        cfg.LogEnabled = _manager.LogEnabled;
        cfg.ShowSatusbar = statusStrip1.Visible;
        cfg.ShowProcess = _manager.ShowProcessName;
        cfg.AlwaysOnTop = btnAlwaysOnTop.Checked;

        cfg.Save();
      }
      finally
      {
        _manager.LogEnabled = false;
      }
    }

    private void btnToggle_Click(object sender, EventArgs e)
    {
      _manager.LogEnabled = !_manager.LogEnabled;
      refreshLoggingStatus();
    }

    private void btnClear_Click(object sender, EventArgs e)
    {
      _manager.ClearMessages();
      _manager.WriteMessagesToWindow();
    }

    private void btnRefresh_Click(object sender, EventArgs e)
    {
      _manager.WriteMessagesToWindow();
    }

    private void btnSave_Click(object sender, EventArgs e)
    {
      string fileName = getFileName();

      if (!string.IsNullOrEmpty(fileName))
      {
        using (StreamWriter outfile = new StreamWriter(fileName))
        {
          StringBuilder sb = new StringBuilder();
          foreach (var m in _manager.GetMessages())
            sb.AppendLine(m);

          outfile.Write(sb.ToString());
        }
      }
    }

    private static string getFileName()
    {
      using (var dialog = new SaveFileDialog())
      {
        dialog.Filter = "sql files|*.sql";
        if (dialog.ShowDialog() == DialogResult.OK)
          return dialog.FileName; 
      }

      return null;
    }

    private void btnStatusBar_Click(object sender, EventArgs e)
    {
      statusStrip1.Visible = !statusStrip1.Visible;
    }

    private void btnAlwaysOnTop_Click(object sender, EventArgs e)
    {
      TopMost = !TopMost;
    }

    private void btnShowProcess_Click(object sender, EventArgs e)
    {
      _manager.ShowProcessName = !_manager.ShowProcessName;
    }

    private void copyFormattedSql(Func<string, string> transformation)
    {
      var formatter = new NHibernate.AdoNet.Util.BasicFormatter();

      string text = string.Empty;

      foreach (var item in gridMessages.SelectedRows.Cast<DataGridViewRow>().OrderBy(row => row.Index))
      {
        var aux = item.Cells[0].Value.ToString();

        if (transformation != null)
          aux = transformation(aux);

        text += formatter.Format(aux);
      }

      if (!string.IsNullOrEmpty(text))
        Clipboard.SetText(text);
    }

    private void copyFormattedSqlToolStripMenuItem_Click(object sender, EventArgs e)
    {
      copyFormattedSql(null);
    }

    private void copyAndReplaceParametersToolStripMenuItem_Click(object sender, EventArgs e)
    {
      copyFormattedSql(s => replaceParameters(s));
    }

    private static string replaceParameters(string sql)
    {
      var parameterParser = new SqlParameterParser();
      var parameterReplacer = new SqlParameterReplacer();
      return parameterReplacer.ReplaceParameters(sql, parameterParser.GetParameters(sql));
    }

    private void selectAllToolStripMenuItem_Click(object sender, EventArgs e)
    {
      gridMessages.SelectAll();
    }
  }
}
